<?php 
if( !defined('CORE_PATH')) die('Access Denied');

class ComponentsManager extends Manager {
	
	// general components
    protected $models = array('Component');
    
    // list of components and their paths
	private $components = array();
	
	public function __construct() {
		parent::__construct('components');
		$this->setItemClassName('Component');

		if( defined('COMPONENTS_PATH') ) {
			
            $components = $this->Component->findAll();
			
			foreach($components as $component) {
				$compPath = $component->getData('ComponentPath');
				
				//if the component path starts with the relative path to the components folder
				// then replace it with the absolute path so it works everywhere
				if( strpos($compPath, '../assets/components') == 0 ) {
					$compPath = str_replace("../assets/components", COMPONENTS_PATH, $compPath );
				}
				
				// save the component information for later use
				$this->components[$component->getData('Component') ] = $compPath;
			}
		}
		
	}
	
	/**
	 * Creates a new component based on the data posted from the CMS
	 */
	public function createNewComponent() {
		$db = $this->getDatabase();
		
		// try to create the component file, if that fails, then we will not even bother to
		// insert the record
		$compPath = kan_fix_path($_POST['ComponentPath']);
		
		// get the dir
		$compDir = dirname($compPath);
		$compDirCreated = false;
		
		// try to create it
		if( (file_exists($compDir) && is_writable($compDir)) || mkdir($compDir) ) {
		  // if we succeeed then well create the component file
		  $compDirCreated = true;
		  
		  // create the new component file
		  $content = isset($_POST['EditorContent']) ? $_POST['EditorContent'] : "<?php \n\t// Your PHP Code Goes Here\n ?>";
		  file_put_contents($compPath, $content );
		} else {
		  die("<b>ERROR:</b> Could Not Create The New Component Directory. <b>../components/</b> is not writable");  
		}
		
		// if the directory is created
		if( $compDirCreated ) {
            $component = new Component( array(
                'ComponentType' => $_POST['ComponentType'],
                'Component' => $_POST['Component'],
                'ComponentName' => $_POST['ComponentName'],
                'Description' => $_POST['Description'],
                'ComponentPath' => $_POST['ComponentPath'],
                'DateAdded' => date('Y-m-d')
            ));
            $component->save();
		}	
	}
	
	/**
	 * Saves the data of the updated component from the CMS to the database.
	 */
	public function updateComponent() {
        $component = new Component( array(
            'id' => $_POST['id'],
            'ComponentType' => $_POST['ComponentType'],
            'Component' => $_POST['Component'],
            'ComponentName' => $_POST['ComponentName'],
            'Description' => $_POST['Description'],
            'ComponentPath' => $_POST['ComponentPath'],
            'DateAdded' => date('Y-m-d')
        ));
        $component->save();
	}
	
	public function importComponent() {
		$_POST['destFileName'] = kan_fix_path($_POST['destFileName']);
		$_POST['destFolder'] = kan_fix_path($_POST['destFolder']);
		$_POST['ArchivePath'] = kan_fix_path($_POST['ArchivePath']);
		
		include_once(CMS_PATH . 'utils/fileUpload.php');
		include_once("FileManager.php");
		
		$fm = new FileManager();
		$db = $this->getDatabase();
		
		$zip = new ZipArchive();
		
		if ($zip->open($_POST['ArchivePath']) === TRUE) {
			
			$index = $zip->locateName("data.json",ZIPARCHIVE::FL_NOCASE|ZIPARCHIVE::FL_NODIR);
			$data = $zip->getFromIndex($index);
			
			$records = json_decode($data);
			
			if( $records !== NULL ) {
				$comp_data = $records->{'component_data'};
				
                // determine if the component is not already present in the database
                $component_count = $this->Component->count(array(
                    'filter' => array('Component' => $comp_data->{'Component'})
                ));
				
				// if no data was returned, then insert the component
				if( $component_count == 0 ) {
                    
                    $component = new Component( array(
                        'ComponentType' => $comp_data->{'ComponentType'},
                        'Component' => $comp_data->{'Component'},
                        'ComponentName' => $comp_data->{'ComponentName'},
                        'Description' => $comp_data->{'Description'},
                        'ComponentPath' => $comp_data->{'ComponentPath'}
                    ));
                    $component->save();
                    
					// extract the zip
					$zip->extractTo( dirname($_POST['ArchivePath']) );
                    
                    // once done, remove the component archive
                    $fm->deleteFile($_POST['ArchivePath']);
				} else {
					echo "<b>" . $row['Component'] . "</b> Component Is Already Present In This KAN Installation.<br />";	
				}
			} else {
				die("Invalid KAN Archive Uploaded. Please check and re-upload");	
			}
			
			$zip->close();
			@unlink( $_POST['ArchivePath'] );
			
		} else {
			die("Invalid KAN Archive Uploaded. Please check and re-upload");
		}
		
		
			
	}
    
    /**
     * Returns the component to render based on the ID supplied
     * 
     * @param string $key
     * @return Component 
     */
    public function getComponent($key) {
        $components = $this->Component->find( array(
            'filter' => array('OR' => array('Component' => $key, 'id' => $key))
        ));
        
        return isset($components[0]) ? $components[0] : NULL;
    }
	
	/**
	 * Returns the path to a component to be displayed. If the component specified
	 * by the $key does not exist, a blank HTML document is returned so that when
	 * included in the page, nothing breaks
	 *
	 * @param String $key the id of the component to retrieve
	 * @return String the path to the component to be displayed
	 */
	public function getComponentPath($key) {
		
		// check the component has been specified, else return a dummy page instead
		$compPath = isset($this->components[$key]) ? $this->components[$key] : COMPONENTS_PATH . 'index.php';
		
		return $compPath;
	}

    /**
     * Returns true if a component with the specific id exists
     * 
     * @param string $key
     * @return boolean
     */
    public function componentExists($key) {
        return isset($this->components[$key]);
    }
	
	/**
	 * Returns all the components in the database as an array of database records
	 */
	public function getComponents($start = 0, $limit = NULL, $options = NULL) {
		$default = array('order' => array('ComponentName'));
		
		if( $options ) {
			$default = array_merge($default, $options);	
		}
		
		return $this->getItems($start, $limit, $default);
	}
	
	public function exportComponent($componentID) {
        $component = new Component($componentID);
		
		$data = array(
			"component_data" => $component->getDataArray()
		);
		
		$exporter = new ExportManager();
		$exporter->zipAndDownloadFolder( kan_fix_path(dirname($component->field('ComponentPath'))), $data );
	}
	
	public function deleteComponent($id) {
	
		if( !is_int($id) || intval($id) <= 0 ) {
			trigger_error("Invalid ID supplied");
			return false;
		}
		
		$component = new Component($id);
		$file = kan_fix_path($component->getData('ComponentPath'));
		
		if( file_exists($file) ) {
			@unlink($file);	
		}
		
		// remove component from database
		$component->delete();
	}
}


?>